﻿using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Events;
using Serilog.Templates;
using System;

namespace ChatBackend.Common.Logs
{
    public static class LogExtend
    {
        public static void AddLog(this IServiceCollection Services)
        {
            Services.AddSingleton<RequestEnricher>();

            var serviceProvider=Services.BuildServiceProvider();

            var systemName = "System";
            var serviceName = "Service";

            var requestLogExpression = "StartsWith(SourceContext, 'Serilog.AspNetCore.RequestLoggingMiddleware')";
            var systemLogExpression = "StartsWith(SourceContext, 'Microsoft.') " +
                "or StartsWith(SourceContext, 'IdentityServer4.') " +
                //"or StartsWith(SourceContext, 'Hangfire.') " +
                //"or StartsWith(SourceContext, 'Volo.Abp.')" +
                "or StartsWith(SourceContext, 'System.Net.')";

            Log.Logger = new LoggerConfiguration()
#if DEBUG
              .MinimumLevel.Debug()
#else
              .MinimumLevel.Information()
#endif
              .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
              .MinimumLevel.Override("IdentityServer4", LogEventLevel.Information)
              .Enrich.FromLogContext()
              .Enrich.WithProperty("SystemName", systemName)
              .Enrich.WithProperty("ServiceName", serviceName)
              .Enrich.With(serviceProvider.GetService<RequestEnricher>())
              .WriteTo.Async(x=>x.Console())//异步输出到控制台
              .WriteTo.Logger(lc => lc//请求日志
                .Filter.ByIncludingOnly(requestLogExpression)
                .Enrich.WithProperty("LogType", "requestlog")
                .WriteTo.Async(c => c.File(
                    formatter: new ExpressionTemplate("{ {@timestamp: @t, systemName: SystemName, serviceName: ServiceName, logType: LogType, traceId: TraceId, connectionId: ConnectionId, requestId: RequestId, spanId: SpanId, parentId: ParentId, logTime: @t, sourceContext: SourceContext, ipAddress: IpAddress, userId: UserId, userName: UserName, requestScheme: RequestScheme, requestPath: RequestPath, requestUrl: RequestUrl, requestMethod: RequestMethod, statusCode: StatusCode, elapsed: Elapsed, requestBody: RequestBody, responseBody: ResponseBody} }\n\n"),
                    path: $"logs/{systemName}-{serviceName}-requestlog-.log",
                    rollingInterval: RollingInterval.Day,
                    retainedFileTimeLimit: TimeSpan.FromDays(2),
                    rollOnFileSizeLimit: true,
                    fileSizeLimitBytes: 52428800, // 50MB
                    retainedFileCountLimit: 2)))
              .WriteTo.Logger(lc => lc//系统日志
                .Filter.ByIncludingOnly(systemLogExpression)
                .Enrich.WithProperty("LogType", "systemlog")
                .WriteTo.Async(c => c.File(
                    formatter: new ExpressionTemplate("{ {@timestamp: @t, systemName: SystemName, serviceName: ServiceName, logType: LogType, traceId: TraceId, connectionId: ConnectionId, requestId: RequestId, spanId: SpanId, parentId: ParentId, logTime: @t, ipAddress: IpAddress, userId: UserId, userName: UserName, level: @l, sourceContext: SourceContext, actionId: ActionId, actionName: ActionName, message: @m, exceptions: @x} }\n\n"),
                    path: $"logs/{systemName}-{serviceName}-systemlog-.log",
                    rollingInterval: RollingInterval.Day,
                    retainedFileTimeLimit: TimeSpan.FromDays(2),
                    rollOnFileSizeLimit: true,
                    fileSizeLimitBytes: 52428800, // 50MB
                    retainedFileCountLimit: 2)))
              //记录自定义业务日志
              .WriteTo.Logger(lc => lc
                    .Filter.ByExcluding($"{requestLogExpression} or {systemLogExpression}")
                    .Enrich.WithProperty("LogType", "businesslog")
                    .WriteTo.Async(c => c.File(
                        formatter: new ExpressionTemplate("{ {@timestamp: @t, systemName: SystemName, serviceName: ServiceName, logType: LogType, traceId: TraceId, connectionId: ConnectionId, requestId: RequestId, spanId: SpanId, parentId: ParentId, logTime: @t, ipAddress: IpAddress, userId: UserId, userName: UserName, level: @l, sourceContext: SourceContext, actionId: ActionId, actionName: ActionName, message: @m, exceptions: @x} }\n\n"),
                        path: $"logs/{systemName}-{serviceName}-businesslog-.log",
                        rollingInterval: RollingInterval.Day,
                        retainedFileTimeLimit: TimeSpan.FromDays(2),
                        rollOnFileSizeLimit: true,
                        fileSizeLimitBytes: 52428800, // 50MB
                        retainedFileCountLimit: 2)))


              .CreateLogger();

            Services.AddSerilog(Log.Logger);
        }
    }
}